<?php
use app\api\service\AccessToken;

// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------

//应用公共文件

/**
 * 计算两点地理坐标之间的距离
 * @param  Decimal $longitude1 起点经度
 * @param  Decimal $latitude1  起点纬度
 * @param  Decimal $longitude2 终点经度
 * @param  Decimal $latitude2  终点纬度
 * @param  Int     $unit       单位 1:米 2:公里
 * @param  Int     $decimal    精度 保留小数位数
 * @return Decimal
 */
function getDistance($localtion,$reference, $unit=2, $decimal=2){
    $localtion=explode(',',$localtion);
    $reference=explode(',',$reference);
    $longitude1=$localtion['0'];
    $latitude1=$localtion['1'];
    $longitude2= $reference['0'];
    $latitude2=$reference['1'];
    $EARTH_RADIUS = 6370.996; // 地球半径系数
    $PI = 3.1415926;
    
    $radLat1 = $latitude1 * $PI / 180.0;
    $radLat2 = $latitude2 * $PI / 180.0;
    
    $radLng1 = $longitude1 * $PI / 180.0;
    $radLng2 = $longitude2 * $PI /180.0;
    
    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;
    
    $distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
    $distance = $distance * $EARTH_RADIUS * 1000;
    
    if($unit==2){
        $distance = $distance / 1000;
    }
    return round($distance, $decimal);
    
}

/**
* 函数用途描述 :去掉二维数组某一元素的某值相同的元素
* @date: 2018年5月23日 下午1:02:53
* @author: 孙洪亮
* @param:  null
* @return: null
*/
function more_array_unique($arr){
    
    foreach($arr[0] as $k => $v){
        $arr_inner_key[]= $k;   //先把二维数组中的内层数组的键值记录在在一维数组中
    }
    foreach ($arr as $k => $v){
        
        $v =  implode(",",$v);
        // $v =join(",",$v);    //降维 用implode()也行
        $temp[$k] =$v;      //保留原来的键值 $temp[]即为不保留原来键值
    }
    $temp =array_unique($temp);    //去重：去掉重复的字符串
    foreach ($temp as $k => $v){
        $a = explode(",",$v);   //拆分后的重组 如：Array( [0] => james [1] => 30 )
        logs("V.TXT", $arr_inner_key);
        logs("V.TXT", $v);
        $arr_after[$k]= array_combine($arr_inner_key,$a);  //将原来的键与值重新合并
    }
    return $arr_after;
}  


function  getRedisConnect(){
    session_start();
    $host = config('host');
    $port = config('port');
    /* 这里替换为实例id和实例password */
    $user = config('user');
    $pwd = config('pwd');
    
    $redis = new \Redis();
    if ($redis->connect($host, $port) == false) {
        die($redis->getLastError());
    }
    /* user:password 拼接成AUTH的密码 */
    if ($redis->auth($user . ":" . $pwd) == false) {
        die($redis->getLastError());
    }
    return  $redis;
}

 function getMemberMessageForOpenid($openid){
    $ACCESS_TOKEN=getAccessToken();
    $OPENID=$openid;
    $url="https://api.weixin.qq.com/cgi-bin/user/info?access_token="."$ACCESS_TOKEN"."&openid=".$OPENID;
    $userInfo=https_request($url);
    unset($userInfo['subscribe_scene']);
    unset($userInfo['qr_scene']);
    unset($userInfo['qr_scene_str']);
    return $userInfo;
    
}


/**
 * @param string $url get请求地址
 * @param int $httpCode 返回状态码
 * @param mixed
 */
//POST字符串到接口,作用是发送字符串到指定地址（带证书）
 function postStr($url,$postfields, $second=30,$aHeader=array()){
    $ch = curl_init();
    $params[CURLOPT_TIMEOUT] = $second;
    $params[CURLOPT_RETURNTRANSFER] = 1;
    //这里设置代理，如果有的话
    //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
    //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
    $params[CURLOPT_URL] = $url;    //请求url地址
    //禁用证书验证
    $params[CURLOPT_SSL_VERIFYPEER] = false;
    $params[CURLOPT_SSL_VERIFYHOST] = false;
    //#$params[CURLOPT_HEADER] = false; //是否返回响应头信息
    //#$params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
    //#$params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
    //以下两种方式需选择一种
    //  第一种方法，cert 与 key 分别属于两个.pem文件
    // 默认格式为PEM，可以注释
    $params[CURLOPT_SSLCERTTYPE]='PEM';
    $params[CURLOPT_SSLCERT]=getcwd().'/apiclient_cert.pem';
    //   默认格式为PEM，可以注释
    $params[CURLOPT_SSLKEYTYPE]='PEM';
    $params[CURLOPT_SSLKEY]=getcwd().'/apiclient_key.pem';
    //第二种方式，两个文件合成一个.pem文件
    // $params[CURLOPT_SSLCERT]=getcwd().'/all.pem';
    $params[CURLOPT_CAINFO]='rootca.pem';
    if( count($aHeader) >= 1 ){
        $params[CURLOPT_HTTPHEADER] = $aHeader;
    }
    $params[CURLOPT_POST] = true;
    
    $params[CURLOPT_POSTFIELDS] = $postfields;
    curl_setopt_array($ch, $params); //传入curl参数
    $content = curl_exec($ch); //执行
    if($content){
        curl_close($ch);
        return $content;
    }
    else {
        $error = curl_errno($ch);
        echo "call faild, errorCode:$error\n";
        curl_close($ch);
        return false;
    }
}
//https请求(GET和POST)
 function https_request($url,$data=null)
{
    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); //将页面以文件流的形式保存
    
    if(!empty($data))
    {
        curl_setopt($ch, CURLOPT_POST, 1);//模拟POST请求
        
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//POST提交内容
    }
    $outopt = curl_exec($ch);
    
    curl_close($ch);
    
    return json_decode($outopt,true);//返回数组结果
}

function curl_get($url,&$httpCode = 0){
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

    //不做证书校验，部署在linux环境下请改位true
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
    $file_contents = curl_exec($ch);
    $httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
    curl_close($ch);
    return $file_contents;
}

function curl_post($url,array $params = array()){
    $data_string = json_encode($params);
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_HEADER,0);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
    curl_setopt($ch,CURLOPT_POST,1);
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$data_string);
    curl_setopt($ch,CURLOPT_HTTPHEADER,
        array(
            'Content-Type: application/json'
        )
    );
    $data = curl_exec($ch);
    curl_close($ch);
    return ($data);
}

function curl_post_raw($url,$rawData){
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_HEADER,0);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
    curl_setopt($ch,CURLOPT_POST,1);
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$rawData);
    curl_setopt($ch,CURLOPT_HTTPHEADER,
        array(
            'Content-Type: text'
        )
    );
    $data = curl_exec($ch);
    curl_close($ch);
    return ($data);
}

//获取随机字符串
 function createNonceStr($length = 32) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i++) {
        $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
}

 function get_php_file($filename) {
    return trim(substr(file_get_contents($filename), 15));
}

 function set_php_file($filename, $content) {
    $fp = fopen($filename, "w");
    fwrite($fp, "<?php exit();?>" . $content);
    fclose($fp);
}

/**
* 函数用途描述 :获取微信或支付宝的支付签名
* @date: 2018年6月25日 上午10:19:06
* @author: 孙洪亮
* @param:  $array(原始数组）,$source（1微信，2支付宝）,$type（签名方式 MD5 RSA）
* @return: null
*/
function getSign($array,$source=1,$type = 'RSA',$getStr=false,$checkRSA2=false){
    //1.去除空值
    array_filter($array);
    //1.5去除sign的值
    if(isset($array['sign'])){
        unset($array['sign']);
    }
    if($checkRSA2){
        if(isset($array['sign_type'])){
            unset($array['sign_type']);
        }
    }else{
        if(isset($array['sign_type']) && $type!='RSA2' ){
            unset($array['sign_type']);
        }
    }
    //2.排序
    ksort($array);
    
    if($source==1){
        $str=arrToUrl($array).'&key='.config('KEY');
        //4.使用MD5或者其他算法进行加密
        //5.转化为大写
        return strtoupper(md5($str));
    }else{
        if($getStr){
            //返回原始字符串不加KEY
            return arrToUrl($array);
        }else{
            if($type=='MD5'){
                $str=arrToUrl($array). config('AliMD5Key');
                //4.使用MD5或者其他算法进行加密
                return  md5($str);
            }else if($type =='RSA'){
                //使用RSA加密
                return  rsaSign(arrToUrl($array), config('APPPRIVATEKEY'));
            }else if($type =='RSA2'){
                //使用RSA加密
                return  rsaSign(arrToUrl($array), config('APPPRIVATEKEY'),'RSA2');
            } 
        }
    }
}

//生成签名的方法
function setSign($array,$source=1,$type = 'RSA'){
    $array['sign']= getSign($array,$source,$type);
    return $array;
}


//链接字符串并且转换字符使中文可以正常显示
function arrToUrl($array,$unencode = true){
    if($unencode){
        return  urldecode(http_build_query($array));
    }else{
        return http_build_query($array);
    }
  
}


/**
* 函数用途描述 :检查签名
* @date: 2018年6月23日 上午10:46:03
* @author: 孙洪亮
* @param:  null
* @return: null
*/
function checkSign($array,$source=1,$type='MD5'){
    //生成新签名
     $sign= getSign($array,$source,$type);
    //和数组中原始签名进行比较
    if($sign==$array['sign']){
        return true;
    }
    else{
        return false;
    }
}

//验证是否来之支付宝的通知
 function isAlipay($arr){
    $str = file_get_contents(config('notify_verify') . $arr['notify_id']);
    if($str == 'true'){
        return true;
    }else{
        return false;
    }
}

// zfb验证交易状态
 function checkAliOrderStatus($arr){
    if($arr['trade_status'] == 'TRADE_SUCCESS' || $arr['trade_status'] == 'TRADE_FINISHED'){
        return true;
    } else {
        return false;
    }
}

/**
 * RSA签名
 * @param $data 待签名数据
 * @param $private_key 私钥字符串
 * return 签名结果
 */
function rsaSign($data, $private_key,$type = 'RSA') {
    
    $search = [
        "-----BEGIN RSA PRIVATE KEY-----",
        "-----END RSA PRIVATE KEY-----",
        "\n",
        "\r",
        "\r\n"
    ];
    
    $private_key=str_replace($search,"",$private_key);
    $private_key=$search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1];
    $res=openssl_get_privatekey($private_key);
    
    if($res)
    {
        if($type == 'RSA'){
            openssl_sign($data, $sign,$res);
        }elseif($type == 'RSA2'){
            //OPENSSL_ALGO_SHA256
            openssl_sign($data, $sign,$res,OPENSSL_ALGO_SHA256);
        }
        openssl_free_key($res);
    }else {
        exit("私钥格式有误");
    }
    $sign = base64_encode($sign);
    return $sign;
}

/**
 * RSA验签
 * @param $data 待签名数据
 * @param $public_key 公钥字符串
 * @param $sign 要校对的的签名结果
 * return 验证结果
 */
function rsaCheck($data, $public_key, $sign,$type = 'RSA')  {
    $search = [
        "-----BEGIN PUBLIC KEY-----",
        "-----END PUBLIC KEY-----",
        "\n",
        "\r",
        "\r\n"
    ];
    $public_key=str_replace($search,"",$public_key);
    $public_key=$search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1];
    $res=openssl_get_publickey($public_key);
    if($res)
    {
        if($type == 'RSA'){
            $result = (bool)openssl_verify($data, base64_decode($sign), $res);
        }elseif($type == 'RSA2'){
            $result = (bool)openssl_verify($data, base64_decode($sign), $res,OPENSSL_ALGO_SHA256);
        }
        openssl_free_key($res);
    }else{
        exit("公钥格式有误!");
    }
    return $result;
}

//记录到文件
 function logs($file,$data){
    // 如果是数字转化为字符串s
    $data=  is_array($data)?print_r($data,true):$data;
    file_put_contents('./logs/'.$file, "\r\n".date("Y-m-d H:i:s",time())."\n".$data,FILE_APPEND);
}

//接受服务器数据
 function getPost(){
    
    return file_get_contents('php://input');
}

//XML->数组
function XmlToArr($xml)
{
    if($xml == '') return '';
    libxml_disable_entity_loader(true);
    $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $arr;
}

//数组转xml
function ArrToXml($arr)
{
    if(!is_array($arr) || count($arr) == 0) return '';
    
    $xml = "<xml>";
    foreach ($arr as $key=>$val)
    {
        if (is_numeric($val)){
            $xml.="<".$key.">".$val."</".$key.">";
        }else{
            $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
        }
    }
    $xml.="</xml>";
    return $xml;
}

//获取AccessToken
 function getAccessToken() {
    // access_token 应该全局存储与更新，以下代码以写入到文件中做示例
    
    $data = json_decode(get_php_file("access_token.php"));
    if ($data->expire_time < time()) {
        $access_token = applyAccessToken();
        if ($access_token) {
            $data->expire_time = time() + 7000;
            $data->access_token = $access_token;
           set_php_file("access_token.php", json_encode($data));
        }
    } else {
        $access_token = $data->access_token;
        $testResult=testAccessToken($access_token);
        if($testResult!='ok'){
            $access_token = applyAccessToken();
            if ($access_token) {
                $data->expire_time = time() + 7000;
                $data->access_token = $access_token;
                set_php_file("access_token.php", json_encode($data));
            }
        }
    }
    return $access_token;
}

function applyAccessToken(){
    // 如果是企业号用以下URL获取access_token
    // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret"
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".config('appid')."&secret=".config('appsecret');
    $result = curl_post($url);
    $result=json_decode($result,true);
   return $result['access_token'];
}


function testAccessToken($access_token){
    $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$access_token";
    $result =json_decode(curl_get($url),true) ;
    return $result['errmsg'];
}


//获取服务器地址
 function getWxServerIp(){
    //1.请求url地址
    $assessToken=getAccessToken();
    $url ="https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=".$assessToken;
    //2.初始化
    $ch = curl_init();
    //3.设置参数
    curl_setopt($ch , CURLOPT_URL, $url);
    curl_setopt($ch , CURLOPT_RETURNTRANSFER, 1);
    //如果获取的token为null，不妨先看看curl_exec返回值是否为false
    //解决办法：跳过SSL证书检查
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    //4.调用接口
    $res = curl_exec($ch);
    var_dump($res);
    
    //5.关闭curl
    
    if(curl_error($ch)){
        var_dump(curl_error($ch));
    }
    curl_close($ch);
    $arr = json_decode($res, true);
    echo "<pre>";
    var_dump($arr);
    echo "</pre>";
}

/**
 * 函数用途描述 :获取访问微信API接口验证票据
 * @date: 2018年2月6日 上午8:45:42
 * @author: 孙洪亮
 * @param: null
 * @return: 返回票据
 */
 function getJsApiTicket() {
    // jsapi_ticket 应该全局存储与更新，以下代码以写入到文件中做示例
    $data = json_decode(get_php_file("jsapi_ticket.php"));
    if ($data->expire_time < time()) {
        $accessToken = getAccessToken();
        // 如果是企业号用以下 URL 获取 ticket
        // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
        $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
        $res = https_request($url);
        $ticket = $res['ticket'];
        if ($ticket) {
            $data->expire_time = time() + 7000;
            $data->jsapi_ticket = $ticket;
           set_php_file("jsapi_ticket.php", json_encode($data));
        }
    } else {
        $ticket = $data->jsapi_ticket;
    }
   
    return $ticket;
}

//生成订单号
  function makeOrderNo(){
    $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
    $orderSn =
    $yCode[intval(date('Y')) - 2017] .
    strtoupper(dechex(date('m'))) .
    date('d') .
    substr(time(), -5) .
    substr(microtime(), 2, 5) .
    sprintf('%02d', rand(0, 99));
    return $orderSn;
}

function hashCode64($str='测试') {
    $str = (string)$str;
    $hash = 0;
    $len = strlen($str);
    if ($len == 0 )
        return $hash;
        
        for ($i = 0; $i < $len; $i++) {
            $h = $hash << 5;
            $h -= $hash;
            $h += ord($str[$i]);
            $hash = $h;
            $hash &= 0xFFFFFFFF;
        }
        return $hash;
}  
//==================================支付宝相关=========================================


